home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / utility1 / gs261src.zip / SCFE.C < prev    next >
C/C++ Source or Header  |  1993-05-13  |  10KB  |  330 lines

  1. /* Copyright (C) 1992 Aladdin Enterprises.  All rights reserved.
  2.  
  3. This file is part of Ghostscript.
  4.  
  5. Ghostscript is distributed in the hope that it will be useful, but
  6. WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
  7. to anyone for the consequences of using it or for whether it serves any
  8. particular purpose or works at all, unless he says so in writing.  Refer
  9. to the Ghostscript General Public License for full details.
  10.  
  11. Everyone is granted permission to copy, modify and redistribute
  12. Ghostscript, but only under the conditions described in the Ghostscript
  13. General Public License.  A copy of this license is supposed to have been
  14. given to you along with Ghostscript so you can know your rights and
  15. responsibilities.  It should be in a file named COPYING.  Among other
  16. things, the copyright notice and this notice must be preserved on all
  17. copies.  */
  18.  
  19. /* scfe.c */
  20. /* CCITTFax encoding filter */
  21. #include "stdio_.h"    /* includes std.h */
  22. #include "memory_.h"
  23. #include "gdebug.h"
  24. #include "scf.h"
  25. #include "stream.h"
  26. #include "sbits.h"
  27.  
  28. /* Imported procedures */
  29. extern int s_filter_write_flush(P1(stream *));
  30.  
  31. /* ------ Macros and support routines ------ */
  32.  
  33. /* Put a code onto the target stream. */
  34. /* Relevant invariants: 0 <= bits_left <= bits_size; only the leftmost */
  35. /* (bits_size - bits_left) bits of bits contain valid data. */
  36.  
  37. #define bits_size (arch_sizeof_int == 2 ? 16 : 32)
  38.  
  39. #ifdef DEBUG
  40. #  define p_c(rp)\
  41.     (gs_debug['w'] ?\
  42.      (dprintf2("[w]0x%x,%d\n", (rp)->code, (rp)->code_length), 0) : 0)
  43. #else
  44. #  define p_c(rp) 0
  45. #endif
  46.  
  47. #define cf_put_code(s, rp)\
  48.   (p_c(rp),\
  49.    ((s->bits_left -= (rp)->code_length) >= 0 ?\
  50.     s->bits += (rp)->code << s->bits_left :\
  51.     cf_put_code_out(s, (rp)->code)))
  52.  
  53. private uint
  54. cf_put_code_out(register stream *s, uint code)
  55. {    int left = s->bits_left;
  56.     const uint cw = s->bits + (code >> -left);
  57.     stream *strm = s->strm;
  58. #if bits_size > 16
  59. #  define cb3 ((byte)(cw >> 24))
  60. #  define cb2 ((byte)(cw >> 16))
  61. #endif
  62. #define cb1 ((byte)(cw >> 8))
  63. #define cb0 ((byte)cw)
  64.     if ( s->reverse_bits )
  65.     {
  66. #if bits_size > 16
  67.         sputc(strm, sbits_reverse_bits[cb3]);
  68.         sputc(strm, sbits_reverse_bits[cb2]);
  69. #endif
  70.         sputc(strm, sbits_reverse_bits[cb1]);
  71.         sputc(strm, sbits_reverse_bits[cb0]);
  72.     }
  73.     else
  74.     {
  75. #if bits_size > 16
  76.         sputc(strm, cb3);
  77.         sputc(strm, cb2);
  78. #  undef cb3
  79. #  undef cb2
  80. #endif
  81.         sputc(strm, cb1);
  82.         sputc(strm, cb0);
  83.     }
  84. #undef cb1
  85. #undef cb0
  86.     return (s->bits = code << (s->bits_left = left + bits_size));
  87. }
  88.  
  89. /* Put a run onto the output stream. */
  90.  
  91. #define cf_put_run(s, lenv, tt, mut)\
  92. {    const cfe_run _ds *rp;\
  93.     if ( lenv >= 64 )\
  94.     {    rp = &mut[lenv >> 6];\
  95.         cf_put_code(s, rp);\
  96.         lenv &= 63;\
  97.     }\
  98.     rp = &tt[lenv];\
  99.     cf_put_code(s, rp);\
  100. }
  101.  
  102. #define cf_put_white_run(s, lenv)\
  103.   cf_put_run(s, lenv, cf_white_termination, cf_white_make_up)
  104.  
  105. #define cf_put_black_run(s, lenv)\
  106.   cf_put_run(s, lenv, cf_black_termination, cf_black_make_up)
  107.  
  108. /* ------ Stream procedures ------ */
  109.       
  110. /*
  111.  * For the 2-D encoding modes, we leave the previous complete scan line
  112.  * at the beginning of the buffer, and start the new data after it.
  113.  */
  114.  
  115. /* Initialize CCITTFaxEncode filter */
  116. void
  117. s_CFE_init(register stream *s, CCITTFax_state *pcfs)
  118. {    s->state.cf = *pcfs;
  119.     if ( s->state.cf.K != 0 )
  120.     {    /* Clear the initial reference line for 2-D encoding. */
  121.         s->cptr = s->cbuf + s->state.cf.raster - 1;
  122.         memset(s->cbuf, (s->state.cf.BlackIs1 ? 0xff : 0), s->state.cf.raster);
  123.         s->state.cf.k_left = -1;
  124.     }
  125.     s->state.cf.k_left = max(s->state.cf.K, 0);
  126.     s->bits = 0;
  127.     s->bits_left = bits_size;
  128. }
  129.  
  130. /* Flush the buffer */
  131. private int cf_encode_1d(P2(stream *, byte *));
  132. private int cf_encode_2d(P3(stream *, byte *, byte *));
  133. private int
  134. s_CFE_write_buf(register stream *s)
  135. {    int raster = s->state.cf.raster;
  136.     byte *prev = s->cbuf;
  137.     byte *p = (s->state.cf.K ? prev + raster : prev);
  138.     byte *limit = s->cptr;
  139.     byte end_mask = 1 << (-s->state.cf.Columns & 7);
  140.     uint count;
  141.     /* Do complete scan lines. */
  142.     while ( (count = limit - p + 1) >= raster )
  143.     {    /* Ensure that the scan line ends with a polarity change. */
  144.         /* This may involve saving and restoring one byte beyond */
  145.         /* the scan line. */
  146.         byte *next = p + raster;
  147.         byte save_next = *next;
  148.         int code;
  149.         if ( end_mask == 1 )        /* set following byte */
  150.             *next = (next[-1] & 1) - 1;
  151.         else if ( next[-1] & end_mask )    /* clear lower bits */
  152.             next[-1] &= -end_mask;
  153.         else                /* set lower bits */
  154.             next[-1] |= end_mask - 1;
  155.         if ( s->state.cf.EncodedByteAlign )
  156.             s->bits_left &= ~7;
  157.         if ( s->state.cf.K > 0 )
  158.         {    /* Group 3, mixed encoding */
  159.             if ( --(s->state.cf.k_left) )
  160.             {    /* Use 2-D encoding */
  161.                 if ( s->state.cf.EndOfLine )
  162.                     cf_put_code(s, &cf2_run_eol_2d);
  163.                 code = cf_encode_2d(s, p, prev);
  164.             }
  165.             else
  166.             {    /* Use 1-D encoding */
  167.                 if ( s->state.cf.EndOfLine )
  168.                     cf_put_code(s, &cf2_run_eol_1d);
  169.                 code = cf_encode_1d(s, p);
  170.                 s->state.cf.k_left = s->state.cf.K;
  171.             }
  172.         }
  173.         else
  174.         {    /* Uniform encoding */
  175.             if ( s->state.cf.EndOfLine )
  176.                 cf_put_code(s, &cf_run_eol);
  177.             code = (s->state.cf.K == 0 ? cf_encode_1d(s, p) :
  178.                 cf_encode_2d(s, p, prev));
  179.         }
  180.         *next = save_next;
  181.         if ( code )
  182.         {    s->end_status = code;
  183.             break;
  184.         }
  185.         prev = p;
  186.         p = next;
  187.     }
  188.     /* Move any remaining partial scan line (and, if 2-D encoding */
  189.     /* is a possibility, the last full scan line) to the beginning */
  190.     /* of the buffer. */
  191.     if ( s->state.cf.K )
  192.         count += raster, p -= raster;
  193.     memcpy(s->cbuf, p, count);
  194.     s->cptr = s->cbuf - 1 + count;
  195.     return 0;
  196. }
  197.  
  198. /* Encode a 1-D scan line. */
  199. private int
  200. cf_encode_1d(stream *s, register byte *p)
  201. {    byte invert = (s->state.cf.BlackIs1 ? 0 : 0xff);
  202.     register uint count;
  203.     uint end_count = s->state.cf.Columns & 7;
  204.     register uint data = *p++ ^ invert;
  205.     for ( count = s->state.cf.raster << 3; count != end_count; )
  206.     {    int white, black;
  207.         /* Parse a white run. */
  208.         white = count;
  209.         skip_white_pixels(data, p, count, invert, w0);
  210.         white -= count;
  211.         cf_put_white_run(s, white);
  212.         if ( count == end_count ) break;
  213.         /* Parse a black run. */
  214.         black = count;
  215.         skip_black_pixels(data, p, count, invert, b0, b1);
  216.         black -= count;
  217.         cf_put_black_run(s, black);
  218.     }
  219.     return 0;
  220. }
  221.  
  222. /* Encode a 2-D scan line. */
  223. private int
  224. cf_encode_2d(stream *s, byte *p, byte *prev_p)
  225. {    byte invert = (s->state.cf.BlackIs1 ? 0 : 0xff);
  226.     byte invert_white = invert;
  227.     register uint count;
  228.     uint end_count = s->state.cf.Columns & 7;
  229.     register uint data = *p++ ^ invert;
  230.     int dist = prev_p - p;
  231.     for ( count = s->state.cf.raster << 3; count != end_count; )
  232.     {    /* If invert == invert_white, white and black have their */
  233.         /* correct meanings; if invert == ~invert_white, */
  234.         /* black and white are interchanged. */
  235.         uint a0, a1, b1;
  236.         uint prev_count = count;
  237.         byte prev_data;
  238.         int diff;
  239.         static const byte count_bit[8] =
  240.             { 0x80, 1, 2, 4, 8, 0x10, 0x20, 0x40 };
  241.         prev_p = p + dist;
  242.         prev_data = prev_p[-1] ^ invert;
  243.         /* Find the a1 and b1 transitions. */
  244.         a0 = count;
  245.         skip_white_pixels(data, p, count, invert, w00);
  246.         a1 = count;
  247.         if ( (prev_data & count_bit[prev_count & 7]) )
  248.         {    /* Look for changing white first. */
  249.             skip_black_pixels(prev_data, prev_p, prev_count, invert, b01, b11);
  250.         }
  251.         if ( prev_count != end_count )
  252.         {    skip_white_pixels(prev_data, prev_p, prev_count, invert, w01);
  253.         }
  254.         b1 = prev_count;
  255.         /* In all the comparisons below, remember that count */
  256.         /* runs downward, not upward, so the comparisons are */
  257.         /* reversed. */
  258.         if ( b1 >= a1 + 2 )
  259.         {    /* Could be a pass mode.  Find b2. */
  260.             if ( prev_count != end_count )
  261.             {    skip_black_pixels(prev_data, prev_p,
  262.                          prev_count, invert, b02, b12);
  263.             }
  264.             if ( prev_count > a1 )
  265.             {    /* Use pass mode. */
  266.                 cf_put_code(s, &cf2_run_pass);
  267.                 count = prev_count;
  268.                 p = prev_p - dist;
  269.                 data = p[-1] ^ invert;
  270.                 continue;
  271.             }
  272.         }
  273.         /* Check for vertical coding. */
  274.         diff = a1 - b1;        /* i.e., logical b1 - a1 */
  275.         if ( diff <= 3 && diff >= -3 )
  276.         {    /* Use vertical coding. */
  277.             cf_put_code(s, &cf2_run_vertical[diff + 3]);
  278.             invert = ~invert;    /* a1 polarity changes */
  279.             continue;
  280.         }
  281.         /* No luck, use horizontal coding. */
  282.         cf_put_code(s, &cf2_run_horizontal);
  283.         if ( count != end_count )
  284.         {    skip_black_pixels(data, p, count, invert, b03, b13);    /* find a2 */
  285.         }
  286.         a0 -= a1;
  287.         a1 -= count;
  288.         if ( invert == invert_white )
  289.         {    cf_put_white_run(s, a0);
  290.             cf_put_black_run(s, a1);
  291.         }
  292.         else
  293.         {    cf_put_black_run(s, a0);
  294.             cf_put_white_run(s, a1);
  295.         }
  296.     }
  297.     return 0;
  298. }
  299.  
  300. /* Close the stream */
  301. private int
  302. s_CFE_close(register stream *s)
  303. {    int code = s_CFE_write_buf(s);
  304.     if ( code == ERRC ) return code;
  305.     if ( s->state.cf.EndOfBlock )
  306.     {    int i = (s->state.cf.K < 0 ? 2 : 6);
  307.         const cfe_run _ds *rp =
  308.             (s->state.cf.K > 0 ? &cf2_run_eol_1d : &cf_run_eol);
  309.         while ( --i >= 0 )
  310.             cf_put_code(s, rp);
  311.     }
  312.     /* Force out the last byte or bytes. */
  313.     while ( s->bits_left < bits_size )
  314.     {    stream *strm = s->strm;
  315.         byte c = (byte)(s->bits >> (bits_size - 8));
  316.         if ( s->reverse_bits )
  317.             c = sbits_reverse_bits[c];
  318.         sputc(strm, c);
  319.         s->bits <<= 8;
  320.         s->bits_left += 8;
  321.     }
  322.     return s_std_close(s);
  323. }
  324.  
  325. /* Stream procedures */
  326. const stream_procs s_CFE_procs =
  327.    {    s_std_noavailable, NULL, s_filter_write_flush, s_CFE_close,
  328.     NULL, s_CFE_write_buf
  329.    };
  330.